/* eslint-disable react-hooks/exhaustive-deps */
import React, { useEffect, useRef, useState } from 'react';
import { useParams } from 'react-router-dom';
import { Form, InputNumber, Spin, DatePicker, Button, message } from 'antd';
import copy from 'copy-to-clipboard';
import dayjs from 'dayjs';
import classNames from 'classnames';

import {
  updateRuleConfigAPI,
  getDayPowerAPI,
  recalculateResultAPI,
  getConfigByDeviceCode,
  saveRecalculateData,
  recalculateAPI,
} from '@/api/visualiza';
import Icon from '@/components/SvgIcon';
import Chart from '@/components/Chart';

import { disabledCommonDate } from '@/utils/antMixin';
import { isNull } from '@/utils/is';
import { formatDuration } from '@/utils';
import { useAutoRequest } from '@/hooks/useAutoLoading';
import { graphic } from '@/utils/echartConfig';

import type { SelectProps } from 'antd';
import type { EChartsOption } from 'echarts';
import type { Dayjs } from 'dayjs';
import type { ChartRef } from '@/components/Chart';

import style from './ruleConfig.module.scss';

/**
 * --配置条件表单--
 */
type StatusValue = {
  T?: number;
  Max?: number;
  Min?: number;
  config?: StatusValue[];
};
type StatusNewValue = {
  shutdown?: StatusValue;
  standby?: StatusValue;
  work?: StatusValue;
  invalidWork?: StatusValue;
};
type StatusProps = {
  labelName?: string;
  color?: string;
  labelFile?: keyof StatusNewValue;
  value?: StatusValue;
  onChange?: (value: StatusValue) => void;
};
const ThresholdInput: React.FC<StatusProps> = ({
  value = {},
  onChange,
  labelFile,
  labelName,
  color,
}) => {
  const [Min, setMin] = useState<number>(0);
  const [Max, setMax] = useState<number>(0);
  const [T, setT] = useState<number>(0);

  const triggerChange = (changedValue: StatusValue) => {
    onChange?.({ Min, Max, T, ...value, ...changedValue });
  };
  const minChangeHandle = (minValue: number | null) => {
    minValue = minValue || 0;
    if (!('Min' in value)) {
      setMin(minValue as number);
    }
    triggerChange({ Min: minValue as number });
  };
  const maxChangeHandle = (maxValue: number | null) => {
    maxValue = maxValue || 0;
    if (!('Max' in value)) {
      setMax(maxValue as number);
    }
    triggerChange({ Max: maxValue as number });
  };
  const TChangeHandle = (TValue: number | null) => {
    TValue = TValue || 0;
    if (!('T' in value)) {
      setT(TValue as number);
    }
    triggerChange({ T: TValue as number });
  };
  return (
    <div className={style['config-input']}>
      <div className={style['input-label']} style={{ color: color }}>
        {labelName}
      </div>
      <div className={style['input-main']}>
        {labelFile === 'invalidWork' ? (
          <>
            <span>极差 ≤ </span>
            <InputNumber
              min={0}
              max={Infinity}
              value={value.Min || Min}
              onChange={minChangeHandle}
            />
          </>
        ) : (
          <div>
            <InputNumber
              min={0}
              max={Infinity}
              value={value.Min || Min}
              onChange={minChangeHandle}
            />
            <span> ≤ 阈值 ≤ </span>
            <InputNumber
              min={0}
              max={Infinity}
              value={value.Max || Max}
              onChange={maxChangeHandle}
            />
            <span style={{ marginLeft: '32px' }}>最小{labelName}时间 = </span>
            <InputNumber
              min={0}
              max={Infinity}
              value={value.T || T}
              onChange={TChangeHandle}
            />
            <span> 秒</span>
          </div>
        )}
      </div>
    </div>
  );
};

/**
 * --工作记录--
 */
type WorkRecordProps = {
  record: API.RecalculateResult['recalculateWorkRecordMap'];
  detail?: Record<string, API.WorkDetailResult[]>;
  code: string;
  text?: string;
};
const WorkRecord: React.FC<WorkRecordProps> = ({
  record,
  detail,
  code,
  text,
}) => {
  // recalculateWorkRecord?.[archivesCode?.value as string]
  // workDetail[archivesCode?.value as string]
  console.log(record, detail);
  return (
    <>
      <div className={style.header}>
        <h1>
          {record?.[code]?.recalculationDate}&nbsp;&nbsp;&nbsp;{text && text}
        </h1>
        <p>
          累积工作时长：
          {detail &&
            formatDuration(
              detail?.[code]?.reduce((prev, next) => {
                return prev + next.duration;
              }, 0) as number
            )}
          <span></span>累计任务数：
          {detail?.[code]?.length || 0}
        </p>
      </div>
      <div className={classNames(style['records-list'], 'flex-auto')}>
        {detail?.[code] &&
          detail[code].map((item, index) => {
            return (
              <div
                key={index}
                style={{
                  display: 'flex',
                  marginBottom: '16px',
                  fontWeight: 'normal',
                }}>
                第 {index + 1} 次工作：
                <span
                  style={{
                    fontWeight: 600,
                    fontVariantNumeric: 'tabular-nums',
                  }}>
                  {item.startTime?.split(' ')[1]}
                </span>
                <Icon
                  name="icon-delimiter"
                  style={{
                    color: '#C9CDD4',
                    margin: '0 15px 0',
                    verticalAlign: 'middle',
                  }}
                />
                <span
                  style={{
                    fontWeight: 600,
                    fontVariantNumeric: 'tabular-nums',
                  }}>
                  {item.endTime?.split(' ')[1]}
                </span>
                <p style={{ marginLeft: '32px' }}>
                  共计工作时长：
                  <span
                    style={{
                      fontWeight: 600,
                      fontVariantNumeric: 'tabular-nums',
                    }}>
                    {formatDuration(item.duration as number)}
                  </span>
                </p>
                {item.validDuration > -1 && (
                  <p style={{ marginLeft: '32px' }}>
                    有效工作时长：
                    <span
                      style={{
                        fontWeight: 600,
                        fontVariantNumeric: 'tabular-nums',
                      }}>
                      {formatDuration(item.validDuration as number)}
                    </span>
                  </p>
                )}
              </div>
            );
          })}
      </div>
    </>
  );
};
let workStatus = {
  shutdown: {
    Name: '关机',
    Value: 0,
  },
  standby: {
    Name: '待机',
    Value: 10,
  },
  work: {
    Name: '工作',
    Value: 20,
  },
  invalidWork: {
    Name: '无效工作',
    Value: 230,
  },
};
const RuleConfig: React.FC = () => {
  const dateFormat = 'YYYY/MM/DD';
  const { deviceCode } = useParams();
  const [ruleConfigForm] = Form.useForm();

  const [powerData, setPowerData] = useState<any[][]>([]);
  const [currentDate, setCurrentDate] = useState<Dayjs | string>(
    dayjs(dayjs().add(-1, 'day')).format(dateFormat)
  );
  const [workDetail, setWorkDetail] =
    useState<Record<string, API.WorkDetailResult[]>>();
  const [recalculateWorkRecord, setRecalculateWorkRecord] = useState<
    API.RecalculateResult['recalculateWorkRecordMap']
  >({});
  const [recalculateStatus, setRecalculateStatus] = useState<number>(0);
  const [recalculateParams, setRecalculateParams] = useState<StatusNewValue>(
    {}
  );
  const [isCalculate, setIsCalculate] = useState<boolean>(false);
  const [archivesCode, setArchivesCode] = useState<{
    value: string;
    label: string;
  }>();
  //采集设备类型编码
  const [productCode, setProductCode] = useState<string>('');
  const [archivesOptions, setArchivesOptions] = useState<
    SelectProps['options']
  >([]);
  const [configData, setConfigData] = useState<Record<string, StatusNewValue>>(
    {}
  );
  const [dateValue, setDateValue] = useState<Dayjs | null>(
    dayjs(dayjs().add(-1, 'day'))
  );
  //是否开启利用有效率
  const [isOpen, setIsOpen] = useState<boolean>(false);

  const chartRef = useRef<ChartRef>(null);
  let powerParams = {
    attributeName: 'power',
    type: 1,
    deviceCode: archivesCode?.label,
    productCode: productCode,
    page: 1,
    pageSize: 100000,
  };

  const [chartLoading, getDayPower] = useAutoRequest(getDayPowerAPI);

  let title = {
    text: `${deviceCode} 设备功率统计`,
    textStyle: {
      color: '#191B27',
      fontWeight: 500,
    },
    top: 16,
    left: 12,
  };
  let option: EChartsOption = {
    tooltip: {
      trigger: 'axis',
      position: function (pt, _, dom, ___, size) {
        // 鼠标在左侧时 tooltip 显示到右侧，鼠标在右侧时 tooltip 显示到左侧。
        let width = (dom as HTMLDivElement).scrollWidth;
        let obj: any = { top: 60, left: pt[0] + 10 };
        if (pt[0] + width >= size.viewSize[0]) {
          obj['left'] = pt[0] - width - 10;
        }
        return obj;
      },
      formatter: (params: any) => {
        let name = `<span style="color: #191B27; font-weight: bold">${params[0].value[0]}</span>`;
        for (let i = 0; i < params.length; i++) {
          name += `<br />${params[i].marker}${params[i].seriesName}<span style="color: #191B27; font-weight: bold;margin-left: 10px">${params[i].value[1]} mW</span>`;
        }
        return name;
      },
    },
    title,
    grid: {
      top: 65,
      left: 65,
      right: 30,
      bottom: 60,
    },
    xAxis: {
      type: 'time',
      // boundaryGap: false,
    },
    yAxis: {
      type: 'value',
    },
    dataZoom: [
      {
        type: 'inside',
        start: 0,
        end: 100,
      },
      {
        start: 0,
        end: 100,
        height: 20,
        xAxisIndex: [0],
        bottom: 10,
        handleIcon:
          'path://M306.1,413c0,2.2-1.8,4-4,4h-59.8c-2.2,0-4-1.8-4-4V200.8c0-2.2,1.8-4,4-4h59.8c2.2,0,4,1.8,4,4V413z',
        handleSize: '100%',
        textStyle: {
          color: '#fff',
        },
      },
    ],
    series: [
      {
        name: '功率',
        type: 'line',
        // smooth: true,
        symbolSize: 0,
        selectedMode: 'single',
        showSymbol: false,
        // symbol: 'none',
        lineStyle: {
          color: '#4E6FF5',
        },
        data: powerData,
      },
    ],
  };
  let timer: any = null;
  useEffect(() => {
    getConfigByDeviceCode({ deviceCode: deviceCode as string }).then(res => {
      setConfigData({});
      setArchivesOptions([]);
      setProductCode(res?.data?.collectionProductCode || '');

      res?.data?.configInfoList?.forEach((item, index) => {
        let configValue = [];
        try {
          configValue = JSON.parse(item.configValue || '[]');
        } catch (error) {
          console.log(error);
        }
        if (index === 0) {
          setArchivesCode({ label: item.deviceCode, value: item.deviceCode });
        }
        let result = {};
        let invalidWork = {};
        configValue.forEach((item: any) => {
          let key = '';
          if (item.Value === 0) {
            key = 'shutdown';
          } else if (item.Value === 10) {
            key = 'standby';
          } else if (item.Value === 20) {
            key = 'work';
            invalidWork = { Min: item.config?.[0].Min || 0 };
          }
          Object.assign(result, {
            [key]: { Min: item.Min, Max: item.Max, T: item.T },
          });
        });
        Object.assign(result, { invalidWork });
        setConfigData(configData => ({
          ...configData,
          [item.deviceCode]: result,
        }));
        setArchivesOptions(archivesOptions => [
          ...archivesOptions!,
          { label: item.deviceCode, value: item.deviceCode },
        ]);
      });
      const enable = res?.data?.deviceTypeDetails?.statusSegmentationEnable;
      setIsOpen(enable === 1);
    });
    getRecalculateResult();
    loop();
    dateChangeHandle(dayjs(dayjs().add(-1, 'day')));
    return () => {
      if (timer) {
        clearInterval(timer);
      }
    };
  }, []);
  useEffect(() => {
    if (archivesCode) {
      Object.entries(configData[archivesCode.label])?.forEach(
        ([key, values]) => {
          ruleConfigForm.setFieldsValue({ [key]: values });
        }
      );
      dateChangeHandle(dateValue);
    }
  }, [archivesCode]);
  useEffect(() => {
    setRecalculateStatus(
      recalculateWorkRecord?.[deviceCode || '']?.status as number
    );
    if (recalculateWorkRecord?.[deviceCode || '']?.status !== 1) {
      if (recalculateWorkRecord?.[deviceCode || '']?.configValue) {
        let configValue = JSON.parse(
          recalculateWorkRecord?.[deviceCode || '']?.configValue!
        );
        console.log(configValue);
        let result = {};
        configValue.forEach((item: any) => {
          let key = '';
          if (item.Value === 0) {
            key = 'shutdown';
          } else if (item.Value === 10) {
            key = 'standby';
          } else if (item.Value === 20) {
            key = 'work';
          }
          let value = { Min: item.Min, Max: item.Max, T: item.T };
          if (item.config) {
            Object.assign(value, { config: item.config });
          }
          Object.assign(result, { [key]: value });
        });
        console.log(result);
        setRecalculateParams(result);
      }
    }
  }, [recalculateWorkRecord, archivesCode]);
  const copyPower = (params: any) => {
    copy(params.data[1]) && message.success('功率值已复制');
  };
  const dateChangeHandle = (date: Dayjs | null) => {
    if (isNull(date) || !archivesCode) {
      return;
    }
    setDateValue(date);
    setCurrentDate(dayjs(date).format(dateFormat));
    let startTime = dayjs(date).startOf('date').format('YYYY/MM/DD HH:mm:ss');
    let endTime = dayjs(date).endOf('date').format('YYYY/MM/DD HH:mm:ss');
    let submitData = { ...powerParams, startTime, endTime };
    getDayPower(submitData).then(res => {
      let result = res?.data?.records.map(item => {
        return [item.time, item.value];
      });
      setPowerData(result);
    });
    getRecalculateResult(dayjs(date).format(dateFormat));
  };
  const checkMinMax = (_: any, value: { Min: number; Max: number }) => {
    if (value.Max >= value.Min) {
      return Promise.resolve();
    }
    return Promise.reject(new Error('请确定大的阈值大于小的'));
  };
  const saveRecalculate = () => {
    let deviceCodes: string[] = [];
    if (archivesOptions?.length! > 1) {
      deviceCodes =
        archivesOptions?.map(item => {
          return item.value as string;
        }) || [];
      deviceCodes.push(deviceCode as string);
    } else {
      deviceCodes.push(deviceCode as string);
    }
    saveRecalculateData({
      deviceCodes,
      recalculationDate:
        recalculateWorkRecord?.[deviceCode || '']?.recalculationDate,
    }).then(() => {
      message.success('保存成功');
    });
  };

  const loop = () => {
    timer = setInterval(() => {
      getRecalculateResult();
    }, 5000);
  };
  const getRecalculateResult = (date: string = currentDate as string) => {
    recalculateResultAPI({
      deviceCode: deviceCode as string,
      recalculationDate: date,
    }).then(res => {
      let workDetailMap = res?.data?.deviceTimeBuckerRecalculateMap;
      let workRecordMap = res?.data?.recalculateWorkRecordMap;
      setWorkDetail(workDetailMap);
      setRecalculateWorkRecord(workRecordMap);
      if (workRecordMap?.[deviceCode as string]?.status === 2) {
        setIsCalculate(false);
      }
      if (
        !workRecordMap ||
        workRecordMap?.[deviceCode as string]?.status === 2
      ) {
        if (timer) {
          clearInterval(timer);
          timer = null;
        }
      }
    });
  };
  const getRecentlyConfigData = () => {
    let configSubmitData = Object.assign({}, configData, {
      [archivesCode?.label as string]: ruleConfigForm.getFieldsValue(),
    });
    setConfigData(configSubmitData);
    return configSubmitData;
  };

  //配置规则
  const getConfigValue = () => {
    let params: API.RecalculateParams['params'] = [];
    let resultData = getRecentlyConfigData();
    Object.entries(resultData).forEach(([key, values]) => {
      let submitData: any[] = [];
      for (let key2 in workStatus) {
        if (key2 === 'invalidWork') continue;
        let newObj = {
          ...workStatus[key2 as keyof typeof workStatus],
          ...values[key2 as keyof StatusNewValue],
        };
        if (key2 === 'work') {
          newObj.config = [
            {
              ...workStatus['invalidWork'],
              ...values['invalidWork'],
            },
          ];
        }
        submitData.push(newObj);
      }

      params.push({
        collectionDeviceCode: key,
        configValue: JSON.stringify(submitData),
        deviceCode: deviceCode as string,
      });
    });
    if (archivesOptions?.length! > 1) {
      params.push({ deviceCode: deviceCode as string });
    }
    return params;
  };
  //重新计算
  const recalculate = () => {
    setIsCalculate(true);
    const params = getConfigValue();
    /**
     * 此处的 archivesCode 是 deviceCode（档案code）
     * deviceCode 是 collectionDeviceCode（传感器code）
     */
    recalculateAPI({
      params,
      recalculationDate: currentDate as string,
    }).then(() => {
      setRecalculateStatus(1);
      loop();
    });
  };
  //保存修改配置规则
  const updateRuleConfig = () => {
    const params = getConfigValue();
    const { collectionDeviceCode, configValue } = params[0];
    updateRuleConfigAPI({
      collectionDeviceCode,
      configValue,
    }).then(() => {
      message.success('保存成功');
    });
  };

  return (
    <div className="flex-auto" style={{ padding: '0 16px' }}>
      <div className={style['chart-wrap']}>
        <div className={style['date-picker']}>
          {/* 支持绑定多个传感器 */}
          {/* <Select
            placeholder="请选择档案编码"
            value={archivesCode}
            labelInValue={true}
            options={archivesOptions}
            onChange={value => {
              setArchivesCode(value);
              getRecentlyConfigData();
            }}
            style={{ marginRight: '16px' }}></Select> */}
          <DatePicker
            disabledDate={disabledCommonDate('day', Infinity, 0)}
            value={dateValue}
            format={dateFormat}
            onChange={dateChangeHandle}
            suffixIcon={
              <Icon
                name="icon-date"
                style={{ color: '#4E5969', fontSize: 14 }}
              />
            }
          />
        </div>
        <div
          style={{
            background: '#ffffff',
            borderRadius: '4px',
            height: '361px',
          }}>
          <Chart
            option={powerData?.length ? option : { graphic, title }}
            ref={chartRef}
            className={style.chart}
            notMerge={true}
            opts={{ useDirtyRect: true }}
            chartStyle={{ height: '100%' }}
            showLoading={chartLoading}
            onEvents={{ click: copyPower }}
          />
        </div>
      </div>
      <div className={style['config-wrap']}>
        <div className={style['config-header']}>
          <h1>配置条件</h1>
          <div>
            {/* {recalculateStatus !== 1 && ( */}
            <Button
              type="default"
              disabled={isCalculate}
              onClick={recalculate}
              style={{ width: 88 }}>
              重新计算
            </Button>
            {/* )} */}
            <Button
              type="primary"
              disabled={isCalculate}
              onClick={updateRuleConfig}
              style={{ marginLeft: 12, width: 88 }}>
              保存
            </Button>
          </div>
        </div>
        <Spin
          spinning={isCalculate}
          tip="结果计算中..."
          indicator={<Icon name="icon-loading" spin />}>
          <div className={style['config-form']}>
            <Form
              className={style['rule-config-form']}
              name="complex-form"
              form={ruleConfigForm}
              // onFinish={saveRecalculate}
              colon={false}
              initialValues={{
                shutdown: {
                  Min: 0,
                  Max: 0,
                  T: 0,
                },
                standby: {
                  Min: 0,
                  Max: 0,
                  T: 0,
                },
                work: {
                  Min: 0,
                  Max: 0,
                  T: 0,
                },
                invalidWork: {
                  Min: 0,
                },
              }}>
              <Form.Item
                name="shutdown"
                label="关机"
                noStyle
                rules={[{ validator: checkMinMax }]}>
                <ThresholdInput labelName="关机" color="#191B27" />
              </Form.Item>
              <Form.Item
                name="standby"
                label="待机"
                noStyle
                rules={[{ validator: checkMinMax }]}>
                <ThresholdInput labelName="待机" color="#FA8C16" />
              </Form.Item>
              <Form.Item
                name="work"
                label="工作"
                noStyle
                rules={[{ validator: checkMinMax }]}>
                <ThresholdInput labelName="工作" color="#0DC191" />
              </Form.Item>
              {isOpen && (
                <Form.Item name="invalidWork" label="无效工作" noStyle>
                  <ThresholdInput
                    labelFile="invalidWork"
                    labelName="无效工作"
                    color="#CCCCCC"
                  />
                </Form.Item>
              )}
            </Form>
          </div>
        </Spin>
      </div>
      {!isCalculate && recalculateStatus === 2 && (
        <div
          className={classNames(style['config-result'], style['config-wrap'])}>
          <div className={style['config-header']}>
            <h1>配置结果计算完成</h1>
          </div>
          <div className={style['calc-result']}>
            <div className={style['calc-params']}>
              <div className={style['config-header']}>
                <h1>上次计算参数</h1>
                <Button type="primary" onClick={saveRecalculate}>
                  保存设置
                </Button>
              </div>
              <div className={style['work-status-params']}>
                {Object.keys(workStatus).map(key => {
                  return (
                    <p key={key}>
                      {workStatus[key as keyof typeof workStatus].Name}
                      {key !== 'invalidWork' ? (
                        <>
                          <span style={{ marginLeft: '16px' }}>
                            {recalculateParams[key as keyof typeof workStatus]
                              ?.Min || 0}
                            &nbsp;&nbsp;≤ 阈值 ≤&nbsp;&nbsp;
                            {recalculateParams[key as keyof typeof workStatus]
                              ?.Max || 0}
                          </span>
                          <span style={{ marginLeft: '16px' }}>
                            最小
                            {workStatus[key as keyof typeof workStatus].Name}
                            时间 ={' '}
                            {recalculateParams[key as keyof typeof workStatus]
                              ?.T || 0}
                          </span>
                          <span> 秒</span>
                        </>
                      ) : (
                        <>
                          <span style={{ marginLeft: '16px' }}>
                            极差 ≤&nbsp;&nbsp;
                          </span>
                          {recalculateParams['work']?.config?.[0]?.Min || 0}
                        </>
                      )}
                    </p>
                  );
                })}
              </div>
            </div>
            <div className={classNames(style.records, 'flex-column')}>
              {workDetail?.[deviceCode || ''] ? (
                <WorkRecord
                  record={recalculateWorkRecord}
                  detail={workDetail}
                  code={deviceCode as string}
                  text="当前结果"
                />
              ) : (
                <div
                  style={{
                    height: '100%',
                    display: 'flex',
                    alignItems: 'center',
                    justifyContent: 'center',
                  }}>
                  暂无数据
                </div>
              )}
            </div>
          </div>
          {archivesOptions?.length! > 1 && (
            <div
              className={classNames(style.records, 'flex-column')}
              style={{ height: '393px', marginTop: '16px', overflow: 'auto' }}>
              <WorkRecord
                record={recalculateWorkRecord}
                detail={workDetail}
                code={deviceCode as string}
                text="整合结果"
              />
            </div>
          )}
        </div>
      )}
    </div>
  );
};

export default RuleConfig;
